#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>

#include "bits.h"
#include "utils.h"
#include "gprs_cipher.h"
#include "gea.h"

void print_check(char * res, uint8_t * out, uint16_t len) {
    uint8_t buf[len];
    osmo_hexparse(res, buf, len);
    if (0 != memcmp(buf, out, len)) {
	printf("FAIL:\n");
	printf("OUT: %s\n", osmo_hexdump_nospc(out, len));
	printf("EXP: %s\n", osmo_hexdump_nospc(buf, len));
    }
    else printf("OK\n");
}

void test_gea3(uint64_t kc, uint32_t iv, int dir, uint16_t len, char * res) {
    printf("%d: %d -> 0x%X ", len, dir, iv);
    uint8_t out[len];
    osmo_gea3(out, len, kc, iv, dir);
    print_check(res, out, len);
}

void test_gea4(char * kc, uint32_t iv, int dir, uint16_t len, char * res) {
    printf("%d: %d -> 0x%X ", len, dir, iv);
    uint8_t out[len], ck[256];
    osmo_hexparse(kc, ck, len);
    osmo_gea4(out, len, ck, iv, dir);
    print_check(res, out, len);
}

int main(int argc, char **argv)
{
    // printf("GEA3 support: %d\n", gprs_cipher_supported(GPRS_ALGO_GEA3));
    // printf("GEA4 support: %d\n", gprs_cipher_supported(GPRS_ALGO_GEA4));
// test vectors according to 3GPP TS 55.217 and TS 55.218
test_gea3(0x2BD6459F82C5BC00LL, 0x8E9421A3, 0, 59, "5F359709DE950D0105B17B6C90194280F880B48DCCDC2AFEED415DBEF4354EEBB21D073CCBBFB2D706BD7AFFD371FC96E3970D143DCB2624054826");
test_gea3(0x952C49104881FF48LL, 0x5064DB71, 0, 59, "FDC03D738C8E14FF0320E59AAF75760799E9DA78DD8F888471C4AEAAC1849633A26CD84F459D265B83D7D9B9A0B1E54F4D75E331640DF19E0DB0E0");
test_gea3(0xEFA8B2229E720C2ALL, 0x4BDBD5E5, 1, 59, "4718A2ADFC90590949DDADAB406EC3B925F1AF1214673909DAAB96BB4C18B1374BB1E99445A81CC856E47C6E49E9DBB9873D0831B2175CA1E109BA");
test_gea3(0x3451F23A43BD2C87LL, 0x893FE14F, 0, 59, "B46B1E284E3F8B63B86D9DF0915CFCEDDF2F061895BF9F82BF2593AE4847E94A4626C393CF8941CE15EA7812690D8415B88C5730FE1F5D410E16A2");
test_gea3(0xCAA2639BE82435CFLL, 0x8FE17885, 1, 59, "9FEFAF155A26CF35603E727CDAA87BA067FD84FF98A50B7FF0EC8E95A0FB70E79CB93DEE2B7E9AB59D050E1262401571F349C68229DDF0DECC4E85");
test_gea3(0x1ACA8B448B767B39LL, 0x4F7BC3B5, 0, 59, "514F6C3A3B5A55CA190092F7BB6E80EF3EDB738FCDCE2FF90BB387DDE75BBC32A04A67B898A3DFB8198FFFC37D437CF69E7F9C13B51A868720E750");
test_gea4("D3C5D592327FB11C4035C6680AF8C6D1", 0x0A3A59B4, 0, 51, "6E217CE41EBEFB5EC8094C15974290065E42BABC9AE35654A53085CE68DFA4426A2FF0AD4AF3341006A3F84B7613ACB4FBDC34");
test_gea4("3D43C388C9581E337FF1F97EB5C1F85E", 0x48571AB9, 0, 59, "FC7314EF00A63ED0116F236C5D25C54EEC56A5B71F9F18B4D7941F84E422ACBDE5EEA9A204679002D14F312F3DEE2A1AC917C3FBDC3696143C0F5D");
test_gea4("A4496A64DF4F399F3B4506814A3E07A1", 0xEB04ADE2, 1, 59, "2AEB5970FB06B718027D048488AAF24FB3B74EA4A6B1242FF85B108FF816A303C72757D9AAD862B835D1D287DBC141D0A28D79D87BB137CD1198CD");

    return 0;
}
